//
// Created by zntx0 on 2025/9/27.
//
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "zJSON.h"


bool zJSON_is_empty(const zJSON* json)
{
    return json->length == 0 || json->content == NULL;
}

bool zJSON_is_number(const zJSON* json)
{
    for (int i = 0; i < json->length; i++)
    {
        if (json->content[i] < '0' || json->content[i] > '9')
            return false;
    }
    return true;
}

bool zJSON_is_string(const zJSON* json)
{
    for (int i = 0; i < json->length; i++)
    {
        if (json->content[i] < 32 || json->content[i] > 126)
            return false;
    }

    return true;
}

bool zJSON_is_bool(const zJSON* json)
{
    if ( strstr(json->content, "true") || strstr(json->content, "false"))
        return true;
    return false;
}


zJSON_PUBLIC(bool) zJSON_IsInvalid(const zJSON * const item)
{
    if (item == NULL) {
        return true;
    }

    if (item->type == zJSON_Invalid || item->content == NULL || item->length <= 0 )
    {
        return true;
    }

    return false;
}

zJSON_PUBLIC(bool) zJSON_IsBool(const zJSON* const item)
{
    if (item == NULL) {
        return false;
    }

    if (item->type == zJSON_Bool)
        return true;

    return true;
}
zJSON_PUBLIC(bool) zJSON_IsNull(const zJSON* const item)
{
    if (item == NULL) {
        return false;
    }

    if (item->type == zJSON_NULL)
        return true;

    return false;
}
zJSON_PUBLIC(bool) zJSON_IsNumber(const zJSON* const item)
{
    if (item == NULL)
        return false;

    if (item->type == zJSON_Number)
        return true;

    return false;
}
zJSON_PUBLIC(bool) zJSON_IsString(const zJSON* const item)
{
    if (item == NULL)
        return false;

    if (item->type == zJSON_String)
        return true;

    return false;
}
zJSON_PUBLIC(bool) zJSON_IsArray(const zJSON* const item)
{
    if (item == NULL)
        return false;

    if (item->type == zJSON_Array)
        return true;

    return false;
}
zJSON_PUBLIC(bool) zJSON_IsObject(const zJSON* const item)
{
    if (item == NULL)
        return false;

    if (item->type == zJSON_Object)
        return true;

    return false;
}
zJSON_PUBLIC(bool) zJSON_IsRaw(const zJSON* const item)
{
    if (item == NULL)
        return false;

    if (item->type == zJSON_Raw)
        return true;

    return false;
}

bool zJSON_isEmpty(const zJSON* item)
{
    if (item == NULL)
        return false;
    return item->length == 0 || item->content == NULL;
}

zJSON_PUBLIC(void) zJSON_Print(const zJSON* json)
{
    if (json == NULL)
        return ;

    printf(">>: ");
    for (int i = 0; i < json->length; i++)
    {
        printf("%c", json->content[i]);
    }
    printf("\n");
}

bool zJSON_strcmp(const zJSON* json, const char* dest)
{
    if (json == NULL)
        return false;

    if ( strlen(dest) != json->length)
        return false;

    for (int i = 0; i < json->length; i++)
    {
        if (json->content[i] != dest[i])
            return false;
    }
    return true;
}

static char zJSON_SearchKeyword(const zJSON* json, int* depth)
{
    for ( int index = *depth; index < json->length; index++) {
        if ( json->content[index] == '{' || json->content[index] == '}'
            || json->content[index] == '[' || json->content[index] == ']'
            || json->content[index] == '"' || json->content[index] == ',' || json->content[index] == ':')
        {
            *depth = index + 1;
            return json->content[index] ;
        }
    }

    return 0;
}

static zJSON zJSON_SearchKey(const zJSON* json, int* depth )
{
    if( zJSON_SearchKeyword(json, depth) != '"') {
        printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
        return (zJSON){.type = zJSON_Invalid};;
    }

    int start_index = *depth;
    if( zJSON_SearchKeyword(json, depth) != '"') {
        printf("%s:%d %s() %s\n", __FILE__, __LINE__,__FUNCTION__, json->content + *depth);
        return (zJSON){.type = zJSON_Invalid};;
    }
    int end_index = *depth;

    if( zJSON_SearchKeyword(json, depth) != ':') {
        printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
        return (zJSON){.type = zJSON_Invalid};;
    }

    return (zJSON){.content = json->content + start_index ,
        .length = end_index - start_index -1,
        .type = zJSON_Key};
}

static int zJSON_SearchValueEnd(const zJSON* json, const char sp1, const char sp2)
{
    int de = 0;
    for(int index = 0; index < json->length; index++) {
        if (json->content[index] == sp1) {
            de++;
        }
        if (json->content[index] == sp2) {
            de--;
            if (de <= 0) {
                return ++index;
            }
        }
    }

    return 0;
}

zJSON zJSON_SearchValue2(const zJSON* json, int* depth )
{
    if (json == NULL )
        return (zJSON){.type = zJSON_Invalid};

    int depth_back = *depth;
    char en = zJSON_SearchKeyword(json, depth);
    if ( en == 0 ) {
        printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
        return (zJSON){.type = zJSON_Invalid};;
    }

    if ( en == '"') {
        if ( zJSON_SearchKeyword(json, depth) != '"') {
            printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
            return (zJSON){.type = zJSON_Invalid};;
        }
        en = zJSON_SearchKeyword(json, depth);
    }

    if( en == ',' || en == '}' || en == ']') {
        (*depth)--;
        const zJSON value = {.content = json->content + depth_back, .length =  *depth - depth_back};

        if ( zJSON_is_number(& value)) {
            return (zJSON){.content = json->content + depth_back, .length = *depth - depth_back, .type = zJSON_Number};
        }
        if ( zJSON_is_string(& value)) {
            return (zJSON){.content = json->content + depth_back, .length = *depth - depth_back, .type = zJSON_String};
        }
        if ( zJSON_is_bool(& value)) {
            return (zJSON){.content = json->content + depth_back, .length = *depth - depth_back, .type = zJSON_Bool};
        }

        printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
        return (zJSON){.type = zJSON_Invalid};;
    }

    if (en == '{') {
        (*depth)--;
        zJSON key = {.content = json->content + *depth,
            .length = json->length - *depth,
            .type = zJSON_Object
        };
        int len  = zJSON_SearchValueEnd( &key, '{', '}');
        if ( len <= 0 )
        {
            printf("%s:%d %s() Error zJSON_Object\n", __FILE__, __LINE__, __FUNCTION__);
            return (zJSON){.type = zJSON_Invalid};
        }
        key.length = len;
        *depth += len;

        printf("%s:%d %s() Debug zJSON_Object\n", __FILE__, __LINE__, __FUNCTION__);
        return key;
    }
    if (en == '[') {
        (*depth)--;

         zJSON key = {
             .content = json->content + *depth,
            .length = json->length - *depth,
             .type = zJSON_Array
         };
        zJSON_Print(&key);
        int len  = zJSON_SearchValueEnd( &key, '[', ']');
        if ( len <= 0 ) {
            printf("%s:%d %s() Error zJSON_Object\n", __FILE__, __LINE__, __FUNCTION__);
            return (zJSON){.type = zJSON_Invalid};
        }
        key.length = len;
        *depth += len;

        printf("%s:%d %s() Debug zJSON_Array \n", __FILE__, __LINE__,__FUNCTION__);
        return key;
    }

    return (zJSON){.type = zJSON_Invalid};;
}



zJSON_PUBLIC(zJSON) zJSON_GetObjectItemV2(const zJSON* const json, const char* const string)
{
    if (json == NULL)
        return (zJSON){.type = zJSON_Invalid};

    int depth = 0;
    char ch = zJSON_SearchKeyword(json, &depth);
    if (  ch !=  '{') {
        printf("%s:%d %s() Error ch %c depth %d\n", __FILE__, __LINE__,__FUNCTION__, ch, depth);
        return (zJSON){.type = zJSON_Invalid};
    }

    while (depth < json->length)
    {
        zJSON key = zJSON_SearchKey(json, &depth );
        if( key.type == zJSON_Invalid ) {
            printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
            return (zJSON){.content = NULL, .length =  0, .type = zJSON_Invalid};
        }

        printf("%s:%d %s() ___key_____", __FILE__, __LINE__,__FUNCTION__);
        zJSON_Print(&key);

        zJSON value = zJSON_SearchValue2(json, &depth);
        if( zJSON_Invalid ==  value.type ) {
            printf("%s:%d %s() Error\n", __FILE__, __LINE__, __FUNCTION__);
            return (zJSON){.content = NULL, .length =  0, .type = zJSON_Invalid};;
        }
        printf("%s:%d %s() ___value_____", __FILE__, __LINE__,__FUNCTION__);
        zJSON_Print(&value);

        if (string != NULL && zJSON_strcmp(&key, string) == true) {
            printf("%s:%d %s() Debug\n", __FILE__, __LINE__,__FUNCTION__);
            return value;
        }

        char en = zJSON_SearchKeyword(json, &depth);
        if ( en == '}') {
            depth--;
            break;
        }
        else if( en != ','  ) {
            printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
            printf("%s:%d %s() %s\n", __FILE__, __LINE__,__FUNCTION__, json->content + depth);
            return (zJSON){.content = NULL, .length =  0, .type = zJSON_Invalid};;
        }
    }

    if ( zJSON_SearchKeyword(json, &depth) != '}') {
        printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
        return (zJSON){.content = NULL, .length =  0, .type = zJSON_Invalid};;
    }

    //*_depth += depth;
    return (zJSON){.content = NULL, .length =  0, .type = zJSON_Invalid};;
}

int zSON_GetArraySizeV2(const zJSON *json )
{
    if (json == NULL)
        return 0;

    int depth = 0;
    int index = 0;
    if ( zJSON_SearchKeyword(json, &depth) !=  '[') {
        return 0;
    }

    while (depth < json->length)
    {
        zJSON value = zJSON_SearchValue2(json, &depth);
        if (value.type == zJSON_Invalid) {
            printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
            return 0;
        }
        zJSON_Print(&value);
        index++;

        char en = zJSON_SearchKeyword(json, &depth);
        if ( en == ']') {
            depth--;
            break;
        }

        if (en != ',') {
            printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
            return 0;
        }
    }

    if ( zJSON_SearchKeyword(json, &depth) != ']') {
        printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
        return 0;
    }

    //*_depth += depth;
    return index;
}


zJSON_PUBLIC(zJSON) zJSON_GetArrayItemV2(const zJSON* json, int item)
{
    if (json == NULL)
        return (zJSON){.type = zJSON_Invalid};

    int depth = 0;
    if ( zJSON_SearchKeyword(json, &depth) !=  '[')
        return (zJSON){.type = zJSON_Invalid};

    int index = 0;
    while (depth < json->length)
    {
        zJSON value = zJSON_SearchValue2(json, &depth);
        if (value.type == zJSON_Invalid) {
            printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
            return (zJSON){.type = zJSON_Invalid};
        }
        zJSON_Print(&value);
        index++;
        if (index == item) {
            return value;
        }

        char en = zJSON_SearchKeyword(json, &depth);
        if ( en == ']') {
            depth--;
            break;
        }

        if (en != ',') {
            printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
            return (zJSON){.type = zJSON_Invalid};;
        }
    }

    if ( zJSON_SearchKeyword(json, &depth) != ']') {
        printf("%s:%d %s() Error\n", __FILE__, __LINE__,__FUNCTION__);
        return (zJSON){.type = zJSON_Invalid};;
    }

    //*_depth += depth;
    return (zJSON){.type = zJSON_Invalid};;
}


// 变参函数：接收多个字符，以'\0'作为结束标志
zJSON_PUBLIC(zJSON) zJSON_GetV2(const zJSON* json, ...)
{
    zJSON contest;
    va_list args;
    va_start(args, NULL);  // 初始化变参列表

    contest.content = json->content;
    contest.length = json->length;
    contest.type = json->type;
    printf("接收的字符串列表：\n");
    zJSON_Print(json);

    // 循环获取字符串，直到遇到NULL结束标志
    while (1) {
        char *str = va_arg(args, char*);
        // 遇到结束标志则退出循环
        if (str == NULL) {
            break;
        }

        printf("- %s\n", str);

        contest = zJSON_GetObjectItem(&contest , str);
        if ( contest.type == zJSON_Invalid ) {
            printf("- %s\n", str);
            break;
        }
        else {
            printf("- >>>>>>>>>>>>>>>>");
            zJSON_Print(&contest);
        }
    }

    va_end(args);  // 清理变参列表
    return contest;
}